﻿/*
 * YangRtcConnection.cpp
 *
 *  Created on: 2021年12月30日
 *      Author: yang
 */

#include <yangwebrtc/YangCRtcConnection.h>
#include <yangutil/yangtype.h>
#include <yangutil/sys/YangSRtp.h>
#include <yangutil/sys/YangLog.h>
#include <yangrtp/YangRtpConstant.h>
#include <yangstream/YangStreamType.h>
int32_t yang_send_avpacket(YangRtcContext* context,YangRtpPacket *pkt,YangBuffer* pbuf) {
	int32_t err = Yang_Ok;
	int32_t nn_encrypt = yang_buffer_pos(pbuf);
	//if(m_publish) m_publish->cache_nack(pkt,pbuf->data,nn_encrypt);
	if(context->pubStream) yang_rtcpublish_cache_nack(context->pubStream,pkt,pbuf->data,nn_encrypt);
	if ((err = yang_enc_rtp(&context->srtp,pbuf->data, &nn_encrypt)) != Yang_Ok) {
		return yang_error_wrap(err, "srtp protect");
	}

	return yang_rtc_sendData(context->udp,pbuf->data, nn_encrypt);
}

int32_t yang_send_nackpacket(YangRtcContext* context,char* data,int32_t nb){
	int32_t err = Yang_Ok;
	int32_t nn_encrypt = nb;

	if ((err = yang_enc_rtp(&context->srtp,data, &nn_encrypt)) != Yang_Ok) {
		return yang_error_wrap(err, "srtp protect");
	}
	return yang_rtc_sendData(context->udp,data, nb);
}
void yang_do_request_keyframe(YangRtcContext* context,uint32_t ssrc){
	if(context&&context->context&&context->context->yang_sendRequest)
			context->context->yang_sendRequest(context->streamConf->uid,ssrc,Yang_Req_Sendkeyframe);

}
int32_t yang_send_rtcp_fb_pli(YangRtcContext* context,uint32_t ssrc) {
	int32_t err = Yang_Ok;
	char buf[kRtpPacketSize];
	YangBuffer stream;
	yang_init_buffer(&stream,buf, sizeof(buf));
	yang_write_1bytes(&stream,0x81);
	yang_write_1bytes(&stream,(char)kPsFb);
	yang_write_2bytes(&stream,2);
	yang_write_4bytes(&stream,ssrc);
	yang_write_4bytes(&stream,ssrc);

	int32_t nb_protected_buf = yang_buffer_pos(&stream);
	if ((err = yang_enc_rtcp(&context->srtp,stream.data, &nb_protected_buf))
			!= Yang_Ok) {
		return yang_error_wrap(err, "protect rtcp psfb pli");
	}

	return yang_rtc_sendData(context->udp,stream.data, nb_protected_buf);
}
int32_t yang_send_rtcp_rr(YangRtcContext* context,uint32_t ssrc, YangReceiveNackBuffer *rtp_queue,
		const uint64_t last_send_systime,  YangNtp* last_send_ntp) {
	int32_t err = Yang_Ok;
	// @see https://tools.ietf.org/html/rfc3550#section-6.4.2
	char buf[kRtpPacketSize];
	//YangBuffer stream(buf, sizeof(buf));
	YangBuffer stream;
	yang_init_buffer(&stream,buf, sizeof(buf));
	yang_write_1bytes(&stream,0x81);
	yang_write_1bytes(&stream,(char)kRR);
	yang_write_2bytes(&stream,7);
	yang_write_4bytes(&stream,ssrc); // TODO: FIXME: Should be 1?

	uint8_t fraction_lost = 0;
	uint32_t cumulative_number_of_packets_lost = 0 & 0x7FFFFF;
	uint32_t extended_highest_sequence =
			yang_nackbuffer_get_extended_highest_sequence(rtp_queue);
			//rtp_queue->get_extended_highest_sequence();
	uint32_t interarrival_jitter = 0;

	uint32_t rr_lsr = 0;
	uint32_t rr_dlsr = 0;

	if (last_send_systime > 0) {
        rr_lsr = (last_send_ntp->ntp_second << 16)
                | (last_send_ntp->ntp_fractions >> 16);
		uint32_t dlsr = (yang_update_system_time() - last_send_systime) / 1000;
		rr_dlsr = ((dlsr / 1000) << 16) | ((dlsr % 1000) * 65536 / 1000);
	}

	yang_write_4bytes(&stream,ssrc);
	yang_write_1bytes(&stream,fraction_lost);
	yang_write_3bytes(&stream,cumulative_number_of_packets_lost);
	yang_write_4bytes(&stream,extended_highest_sequence);
	yang_write_4bytes(&stream,interarrival_jitter);
	yang_write_4bytes(&stream,rr_lsr);
	yang_write_4bytes(&stream,rr_dlsr);


	int32_t nb_protected_buf = yang_buffer_pos(&stream);
	if ((err = yang_enc_rtcp(&context->srtp,stream.data, &nb_protected_buf))
			!= Yang_Ok) {
		return yang_error_wrap(err, "protect rtcp rr");
	}

	return yang_rtc_sendData(context->udp,stream.data, nb_protected_buf);
}

int32_t yang_send_rtcp_xr_rrtr(YangRtcContext* context,uint32_t ssrc) {
	int32_t err = Yang_Ok;

	/*
	 @see: http://www.rfc-editor.org/rfc/rfc3611.html#section-2

	 0                   1                   2                   3
	 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
	 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 |V=2|P|reserved |   PT=XR=207   |             length            |
	 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 |                              SSRC                             |
	 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 :                         report blocks                         :
	 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

	 @see: http://www.rfc-editor.org/rfc/rfc3611.html#section-4.4

	 0                   1                   2                   3
	 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
	 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 |     BT=4      |   reserved    |       block length = 2        |
	 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 |              NTP timestamp, most significant word             |
	 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 |             NTP timestamp, least significant word             |
	 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
	 */
	int64_t now = yang_update_system_time();
	YangNtp cur_ntp;
	yang_ntp_from_time_ms(&cur_ntp,now / 1000);

	char buf[kRtpPacketSize];
	//YangBuffer stream(buf, sizeof(buf));
	YangBuffer stream;
	yang_init_buffer(&stream,buf, sizeof(buf));
	yang_write_1bytes(&stream,0x80);
		yang_write_1bytes(&stream,(char)kXR);
		yang_write_2bytes(&stream,4);
		yang_write_4bytes(&stream,ssrc);
		yang_write_1bytes(&stream,4);
		yang_write_1bytes(&stream,0);
		yang_write_2bytes(&stream,2);
	    yang_write_4bytes(&stream,cur_ntp.ntp_second);
	    yang_write_4bytes(&stream,cur_ntp.ntp_fractions);

	int32_t nb_protected_buf = yang_buffer_pos(&stream);
	if ((err = yang_enc_rtcp(&context->srtp,stream.data, &nb_protected_buf))
			!= Yang_Ok) {
		return yang_error_wrap(err, "protect rtcp xr");
	}

	return yang_rtc_sendData(context->udp,stream.data, nb_protected_buf);
}

int32_t yang_check_send_nacks(YangRtcContext* context,YangRtpRecvNack *nack, uint32_t ssrc,
		uint32_t *sent_nacks, uint32_t *timeout_nacks) {

	//YangRtcpNack rtcpNack(ssrc);
	//rtcpNack.set_media_ssrc(ssrc);
	YangRtcpCommon rtcp;
	memset(&rtcp,0,sizeof(YangRtcpCommon));
	yang_init_rtcpNack(&rtcp,ssrc);
	//nack->get_nack_seqs(rtcp.nack, timeout_nacks);
	yang_recvnack_get_nack_seqs(nack,rtcp.nack, timeout_nacks);
	if (rtcp.nack->vlen==0) {
		return Yang_Ok;
	}

	char buf[kRtcpPacketSize];
	YangBuffer stream;
	yang_init_buffer(&stream,buf, sizeof(buf));


	yang_encode_rtcpNack(&rtcp,&stream);
	int32_t nb_protected_buf = yang_buffer_pos(&stream);
	yang_enc_rtcp(&context->srtp,stream.data, &nb_protected_buf);
	yang_rtc_sendData(context->udp,stream.data, nb_protected_buf);
	yang_destroy_rtcpNack(&rtcp);
    return Yang_Ok;
}
